package com.itheima.dfs.controller;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.constants.SystemConstants;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.common.vo.ResultVo;
import com.itheima.dfs.enums.DFSType;
import com.itheima.dfs.model.BaseFileModel;
import com.itheima.dfs.strategy.DfsTemplateStrategyContext;
import com.itheima.dfs.template.DfsTemplate;
import com.itheima.wemedia.feign.WmMaterialFeign;
import com.itheima.wemedia.pojo.WmMaterial;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @version 1.0
 * @description 说明
 * @package com.itheima.dfs.controller
 */
@RestController
@RequestMapping("/dfs")
@Slf4j
public class FileController {

    /**
     * 使用模块模式
     * 需要使用FastDFS时，属性名fastDfsTemplate
     * 需要使用Oss存储时，属性名为ossFileTemplate
     *        MinIO            MinIoTemplate
     */
    /*@Resource
    private DfsTemplate fastDfsTemplate;*/
    /**
     * 策略模式中的环境
     */
    @Resource
    private DfsTemplateStrategyContext context;

    @Value("${dfs.type}")
    private String dfsType;

    @Resource
    private WmMaterialFeign wmMaterialFeign;

    /**
     * 上传文件
     *
     * @param 【注意】参数名不能修改，必须为multipartFile
     * @return
     */
    @PostMapping("/upload")
    public ResultVo upload(MultipartFile multipartFile) {

        // 支持的类型
        DFSType dfsType = DFSType.valueOf(this.dfsType);
        DfsTemplate dfsTemplate = context.getTemplate(dfsType);

        // 请求来源判断
        String from = RequestContextUtil.getHeader(SystemConstants.USER_HEADER_FROM);
        if (StringUtils.isEmpty(from)) {
            // 没有经过自媒体网关，不给上传
            return ResultVo.bizError("拒绝非法上传!");
        }

        try {
            // 文件输入流
            InputStream is = multipartFile.getInputStream();
            // 文件的大小
            long size = multipartFile.getSize();

            BaseFileModel baseFileModel = new BaseFileModel("itheima",size,
                multipartFile.getOriginalFilename(),multipartFile.getBytes());

            // 上传文件
            String fileId = dfsTemplate.uploadFile(baseFileModel);

            log.info("上传了文件 FileID=: {}", fileId);

            // 判断是否是自媒体来的
            if (from.equals(SystemConstants.WEMEDIA_PIC)) {
                // 远程调用添加素材记录
                addWmMaterial(fileId);
            }

            // 返回 {url: 全路径} => map 要么是一个java bean
            Map<String, String> map = Collections.singletonMap("url", dfsTemplate.getAccessServerAddr() + fileId);
            return ResultVo.ok(map);
        } catch (IOException e) {
            log.error("FastDFS上传文件失败!", e);
        }
        return ResultVo.bizError("上传文件失败!");
    }

    /**
     * 远程调用添加素材记录
     *
     * @param fileId
     */
    private void addWmMaterial(String fileId) {
        // 创建素材对象
        WmMaterial pojo = new WmMaterial();
        // 设置属性值
        pojo.setUserId(RequestContextUtil.getUserId());
        pojo.setUrl(fileId);
        pojo.setType(0);// 0：图片
        pojo.setIsCollection(0); // 未收藏
        pojo.setCreatedTime(LocalDateTime.now());
        // 远程调用
        // 判断结果，如果出错则要抛异常
        ResultVo addResult = wmMaterialFeign.addWmMaterial(pojo);
        if (!addResult.isSuccess()) {
            log.error("远程调用自媒体，添加素材失败!{}", addResult.getErrorMessage());
            throw new LeadNewsException("上传文件失败!");
        }
    }

    /**
     * 批量下载文件
     *
     * @param urls
     * @return
     */
    @PostMapping("/download")
    public ResultVo<List<byte[]>> download(@RequestBody Collection<String> urls) {
        // 支持的类型
        DFSType dfsType = DFSType.valueOf(this.dfsType);
        DfsTemplate dfsTemplate = context.getTemplate(dfsType);

        return ResultVo.ok(dfsTemplate.download(urls));
    }
}
